/*    
    OpenMheg - A free MHEG-5 library
    Copyright (C) 2008 Dharmesh Malam

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.Text;
using Core.Model.Events;
using Core.Model.Data.Generics;
using Core.Model.Links;
using Core.Model.Data.Variables;
using Core.Model.Actions;

namespace Core.Model
{
    public class TokenGroup : Presentable, TokenManager
    {

        #region  Exchanged attributes
        private List<TokenGroupItem> tokenGroupItems = new List<TokenGroupItem>();

        public List<TokenGroupItem> TokenGroupItems
        {
            get { return tokenGroupItems; }
            set { tokenGroupItems = value; }
        }
        private List<Action> noTokenActionSlots = new List<Action>();

        public List<Action> NoTokenActionSlots
        {
            get { return noTokenActionSlots; }
            set { noTokenActionSlots = value; }
        }

        private List<List<int>> movementTable = new List<List<int>>();

        public List<List<int>> MovementTable
        {
            get { return movementTable; }
            set { movementTable = value; }
        }

        public override void InittInternalAttributes ()
        {
            base.InittInternalAttributes();
        }

        #endregion

        #region  Event processing

        //private List<Link> tokenMovedFrom = new List<Link>();

        //internal List<Link> TokenMovedFrom
        //{
        //    get { return tokenMovedFrom; }
        //    set { tokenMovedFrom = value; }
        //}

        //private List<Link> tokenMovedTo = new List<Link>();

        //internal List<Link> TokenMovedTo
        //{
        //    get { return tokenMovedTo; }
        //    set { tokenMovedTo = value; }
        //}

        //public override void handle ( Events.Event evnt )
        //{
        //    switch ( evnt.Type )
        //    {
        //        case enumEvents.TokenMovedFrom:
        //            foreach ( Link l in tokenMovedFrom )
        //                l.fire( ( ( TokenMovedFrom ) evnt ).Data );
        //            break;

        //        case enumEvents.TokenMovedTo:
        //            foreach ( Link l in tokenMovedTo )
        //                l.fire( ( ( TokenMovedTo ) evnt ).Data );
        //            break;

        //        default:
        //            base.handle( evnt );
        //            break;

        //    }

        //}

        //public override void addLink ( Link link )
        //{
        //    switch ( link.LinkCondition.EventType )
        //    {
        //        case enumEvents.TokenMovedFrom:
        //            tokenMovedFrom.Add( link );
        //            break;

        //        case enumEvents.TokenMovedTo:
        //            tokenMovedTo.Add( link );
        //            break;

        //        default:
        //            base.addLink( link );
        //            break;
        //    }
        //}
        #endregion

        #region  Internal attributes

        private int tokenPosition = 1;

        public int TokenPosition
        {
            get { return tokenPosition; }
            // set { tokenPosition = value; }
        }

        #endregion

        #region  Internal behaviours

        public override void Activate ()
        {
            if ( RunningStatus )
                return;

            base.Activate();

            foreach ( TokenGroupItem tgi in TokenGroupItems )
                ( ( Visible ) MHEGEngine.Instance.Find( tgi.ObjectRef ) ).Activate();

            MHEGEngine.Instance.Handle( new TokenMovedTo( this, tokenPosition ) );

            RunningStatus = true;
            MHEGEngine.Instance.Handle( new IsRunning( this ) );
        }

        public override void Deactivate ()
        {
            if ( !RunningStatus )
                return;

            MHEGEngine.Instance.Handle( new TokenMovedFrom( this, tokenPosition ) );
            base.Deactivate();
        }

        public void TransferToken ( int targetElement )
        {
            MHEGEngine.Instance.Handle( new TokenMovedFrom( this, tokenPosition ) );

            tokenPosition = targetElement;

            MHEGEngine.Instance.Handle( new TokenMovedTo( this, tokenPosition ) );
        }

        public void TransferToken ( GenericInteger targetElement )
        {
            TransferToken( targetElement.Value );
        }

        #endregion

        #region  Actions

        public void Move ( GenericInteger movementId )
        {
            int newPosition = movementTable [movementId.Value-1] [tokenPosition-1];

            if ( newPosition != tokenPosition )
                TransferToken( newPosition );
        }

        public void MoveTo ( GenericInteger index )
        {
            if ( index.Value != tokenPosition )
                TransferToken( index );
        }

        public void GetTokenPosition ( IntegerVariable tokenPosition )
        {
            tokenPosition.Value =  this.tokenPosition;
        }

        public void CallActionSlot ( GenericInteger index )
        {
            List<Actions.Action> activeList = null;

            if ( tokenPosition == 0 )
                activeList = noTokenActionSlots;
            else if ( tokenPosition <= tokenGroupItems.Count  )
                activeList = tokenGroupItems [tokenPosition-1].ActionSlots;

            if ( activeList != null &&  index.Value <= activeList.Count )
            {
                Actions.Action action = activeList [index.Value-1];

                if ( action != null )
                    MHEGEngine.Instance.QActions( action );
            }
            else
            {
                throw new Exception( "Could not locate index" );
                //log.warning("Could not locate an action at index " + index.Value + " for TokenPosition " + getTokenPosition());
            }
        }

        #endregion

    }
}